{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 🎬 Movie Buff Assistant with aisuite + MCP Tools\n",
    "\n",
    "Build your own movie recommendation assistant that:\n",
    "1. 🔍 Researches movies, actors, and directors\n",
    "2. 🧠 Remembers your preferences and watch history\n",
    "3. 💡 Gives personalized recommendations\n",
    "\n",
    "## How This Works\n",
    "\n",
    "When you pass MCP tools to aisuite:\n",
    "1. **aisuite handles the glue work** - converts MCP tool specs to the format your LLM needs (OpenAI, Anthropic, etc.)\n",
    "2. **Automatic execution** - when the LLM requests a tool, aisuite calls the MCP server and returns results\n",
    "3. **You just write natural prompts** - no need to worry about tool schemas or execution logic!\n",
    "\n",
    "This is the power of aisuite + MCP: unified tool calling across any LLM provider.\n",
    "\n",
    "**What you need:**\n",
    "- OpenAI API key (add to `.env` file)\n",
    "- Python with `uv` installed (for fetch MCP server)\n",
    "- Node.js/npx installed (for memory MCP server)\n",
    "\n",
    "**Installation:**\n",
    "```bash\n",
    "pip install aisuite python-dotenv\n",
    "pip install 'aisuite[mcp]'  # Includes MCP client + nest_asyncio for Jupyter support\n",
    "pip install uv  # For fetch MCP server\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✓ Ready to discover movies!\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "from pathlib import Path\n",
    "\n",
    "# Add parent directory to Path - to pick up aisuite for development\n",
    "# Skip this step if you're running from an installed package\n",
    "repo_root = Path().absolute().parent.parent\n",
    "if str(repo_root) not in sys.path:\n",
    "    sys.path.insert(0, str(repo_root))\n",
    "\n",
    "from dotenv import load_dotenv\n",
    "from aisuite import Client\n",
    "from aisuite.mcp import MCPClient  # Needed to connect to MCP servers.\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "# Verify API key\n",
    "if not os.getenv(\"OPENAI_API_KEY\"):\n",
    "    raise ValueError(\"Add OPENAI_API_KEY to .env file!\")\n",
    "\n",
    "print(\"✓ Ready to discover movies!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1: Set Up Your Movie Assistant\n",
    "\n",
    "Provide tools from 2 different MCP servers to the LLM.\n",
    "- **Fetch**: Get movie info from the web (IMDb, Wikipedia, reviews)\n",
    "- **Memory**: Remember what movies you like and dislike"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fetch server ready - can research movies from the web\n",
      "Memory server ready - will remember your preferences\n",
      "📁 Memories stored in: /Users/rohit/fleet/leclerc/aisuite-prs/aisuite-main/aisuite/examples/agents/movie_memory.jsonl\n"
     ]
    }
   ],
   "source": [
    "# Start fetch server (for getting movie data from the web)\n",
    "fetch_mcp = MCPClient(\n",
    "    command=\"uvx\",\n",
    "    args=[\"mcp-server-fetch\"],\n",
    "    name=\"fetch\"\n",
    ")\n",
    "\n",
    "# Set up memory file for your movie preferences\n",
    "memory_file = os.path.join(os.getcwd(), \"movie_memory.jsonl\")\n",
    "# Start memory server (for remembering your preferences)\n",
    "memory_mcp = MCPClient(\n",
    "    command=\"npx\",\n",
    "    args=[\"-y\", \"@modelcontextprotocol/server-memory\"],\n",
    "    env={\"MEMORY_FILE_PATH\": memory_file},\n",
    "    name=\"memory\"\n",
    ")\n",
    "\n",
    "print(\"Fetch server ready - can research movies from the web\")\n",
    "print(\"Memory server ready - will remember your preferences\")\n",
    "print(f\"📁 Memories stored in: {memory_file}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Research a Movie & Store Your Opinion\n",
    "\n",
    "Let's ask the assistant to research a movie and remember whether you liked it!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "============================================================\n",
      "🎬 MOVIE RESEARCH\n",
      "============================================================\n",
      "🎬 I'm thrilled to share some fascinating facts about *Inception*, a cinematic gem!\n",
      "\n",
      "1. **A Global Shooting Journey**: Did you know that *Inception* was filmed in six different countries? The production kicked off in Tokyo and wrapped up in Canada, making it a truly international affair! 🌏\n",
      "\n",
      "2. **A Decade in the Making**: Director Christopher Nolan initially penned an 80-page treatment for *Inception* after completing *Insomnia* back in 2002. But he decided to hone his craft with other projects, like *Batman Begins* and *The Dark Knight*, before finally bringing his dream-stealing concept to life. Talk about dedication! 📜✍️\n",
      "\n",
      "3. **Mind-Bending Visuals**: The film is renowned for its stunning visual effects, especially the iconic scenes where the streets of Paris fold up like a mind-bending puzzle. It's a visual masterpiece that keeps you in awe! 🎥✨\n",
      "\n",
      "I've enthusiastically recorded that *Inception* is a movie I love for its complex plot and visual brilliance. It aligns perfectly with my liking for sci-fi, intricate narratives, and, of course, Christopher Nolan's exceptional filmmaking style! 🎬💕\n"
     ]
    }
   ],
   "source": [
    "client = Client()\n",
    "\n",
    "# Combine tools from both servers\n",
    "all_tools = fetch_mcp.get_callable_tools() + memory_mcp.get_callable_tools()\n",
    "\n",
    "response = client.chat.completions.create(\n",
    "    model=\"openai:gpt-4o\",\n",
    "    messages=[{\n",
    "        \"role\": \"user\",\n",
    "        \"content\": \"\"\"Research the movie 'Inception' from https://www.imdb.com/title/tt1375666/ or Wikipedia.\n",
    "        \n",
    "        Then:\n",
    "        1. Store 'Inception' as a movie entity I loved\n",
    "        2. Store that I like: complex plots, sci-fi, Christopher Nolan movies\n",
    "        3. Add observations about why it's great (mind-bending, great visuals, etc.)\n",
    "        4. Tell me 2-3 interesting facts you found\n",
    "        \n",
    "        Be enthusiastic and conversational!\"\"\"\n",
    "    }],\n",
    "    tools=all_tools,\n",
    "    max_turns=10\n",
    ")\n",
    "\n",
    "print(\"=\"*60)\n",
    "print(\"🎬 MOVIE RESEARCH\")\n",
    "print(\"=\"*60)\n",
    "print(response.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 3: Get Personalized Recommendations\n",
    "\n",
    "Now ask for recommendations based on what it remembers about your tastes!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "============================================================\n",
      "💡 PERSONALIZED RECOMMENDATIONS\n",
      "============================================================\n",
      "🎬 Hey there, movie buff! Here's a quick refresher on the movies you loved and your go-to interests:\n",
      "\n",
      "**Movies You Loved:**\n",
      "1. **Inception**: A mind-bending thrill ride directed by the genius Christopher Nolan. It's got all the layers, twists, and turns you love!\n",
      "2. **Arrival**: This one’s a top recommendation for you because of its cerebral, first-contact story, wrapped in sci-fi brilliance!\n",
      "\n",
      "**Your Movie Interests:**\n",
      "1. **Complex Plots**: You love narratives that make you think and keep you on the edge of your seat.\n",
      "2. **Sci-Fi**: Exploring futuristic themes and imaginative worlds is right up your alley.\n",
      "3. **Christopher Nolan Movies**: His creative storytelling and direction style never fail to capture your attention.\n",
      "\n",
      "🎥 **Movie Recommendations You'll Probably Enjoy:**\n",
      "\n",
      "1. **Blade Runner 2049**: A breathtaking continuation of a sci-fi classic, directed by Denis Villeneuve. The movie's stunning visuals, intricate plot, and philosophical questions about humanity will have you entranced!\n",
      "   - **Why You'll Love It**: With its rich storytelling, complex themes, and connection to Denis Villeneuve (who directed another favorite, Arrival), this film fits your love for thought-provoking sci-fi perfectly!\n",
      "\n",
      "2. **Interstellar**: Another Nolan masterpiece! This epic adventure takes you through space and time with mind-blowing scientific concepts and emotional depth.\n",
      "   - **Why It's Perfect for You**: Featuring Nolan’s signature storytelling, coupled with complex theoretical physics, it’s a movie that’ll satisfy your craving for a narrative that challenges and engages.\n",
      "\n",
      "3. **The Prestige**: Dive into the world of magic and bitter rivalries with this gripping film by Christopher Nolan. Full of twists and turns, it's a story that'll keep you guessing.\n",
      "   - **Why You'll Enjoy It**: With its layered storytelling and mystery, it taps right into your love for complex plots and Nolan’s directional genius!\n",
      "\n",
      "Enjoy these cinematic adventures! Grab some popcorn and prepare to be amazed! 🍿✨\n"
     ]
    }
   ],
   "source": [
    "response = client.chat.completions.create(\n",
    "    model=\"openai:gpt-4o\",\n",
    "    messages=[{\n",
    "        \"role\": \"user\",\n",
    "        \"content\": \"\"\"Tell me what you know about my movie preferences from memory, and suggest something new:\n",
    "        \n",
    "        1. Remind me what movies I liked\n",
    "        2. Suggest 3 movies I'd probably enjoy\n",
    "        3. Explain why each recommendation fits my taste\n",
    "        \n",
    "        Be enthusiastic like a friend recommending movies!\"\"\"\n",
    "    }],\n",
    "    tools=memory_mcp.get_callable_tools(),\n",
    "    max_turns=10\n",
    ")\n",
    "\n",
    "print(\"=\"*60)\n",
    "print(\"💡 PERSONALIZED RECOMMENDATIONS\")\n",
    "print(\"=\"*60)\n",
    "print(response.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 4: Research a Director's Filmography\n",
    "\n",
    "Let's explore a Director's work and see if the LLM can recommend something based on the limited preferences I saved earlier:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "============================================================\n",
      "🎥 DIRECTOR DEEP DIVE\n",
      "============================================================\n",
      "### Denis Villeneuve's Major Films\n",
      "\n",
      "Denis Villeneuve, a Canadian director, is renowned for his cerebral thrillers and large-scale science fiction films. Here is a list of his major films:\n",
      "\n",
      "1. **Incendies (2010)** - A powerful drama exploring family secrets and the horrors of war.\n",
      "2. **Prisoners (2013)** - A gripping thriller about a father's desperate search for his missing daughter.\n",
      "3. **Enemy (2013)** - A psychological thriller exploring themes of identity and duality.\n",
      "4. **Sicario (2015)** - A tense thriller about the drug war on the U.S.-Mexico border.\n",
      "5. **Arrival (2016)** - A cerebral first-contact story about language, time, and choice.\n",
      "6. **Blade Runner 2049 (2017)** - A visually stunning sequel to the classic sci-fi film, delving into the nature of humanity.\n",
      "7. **Dune (2021)** - An epic adaptation of the renowned science fiction novel.\n",
      "8. **Dune: Part Two (2024)** - The continuation of the epic sci-fi saga.\n",
      "\n",
      "### Personalized Film Recommendation\n",
      "\n",
      "Based on your love of complex plots, science-fiction, and storytelling akin to Christopher Nolan's style, you would likely love Denis Villeneuve's **Arrival (2016)**. It's not just a sci-fi film; it's a profound exploration of language and time with an elegant puzzle-box structure that will keep you engaged and intrigued throughout.\n",
      "\n",
      "### Storing Your Top Recommendation\n",
      "\n",
      "I will now store **Arrival (2016)** as your top film recommendation in memory, seeing as it fits perfectly with your interests and past movie preferences. Enjoy discovering Denis Villeneuve's masterful storytelling!\n"
     ]
    }
   ],
   "source": [
    "response = client.chat.completions.create(\n",
    "    model=\"openai:gpt-4o\",\n",
    "    messages=[{\n",
    "        \"role\": \"user\",\n",
    "        \"content\": \"\"\"Research Denis Villeneuve's filmography from IMDb or Wikipedia.\n",
    "        \n",
    "        1. List his major films\n",
    "        2. Based on my interests and moveis I liked earlier (check memory!), which of his films would I love?\n",
    "        3. Store the top recommendation in memory\n",
    "        \n",
    "        Make it exciting - I love discovering new directors!\"\"\"\n",
    "    }],\n",
    "    tools=all_tools,\n",
    "    max_turns=10\n",
    ")\n",
    "\n",
    "print(\"=\"*60)\n",
    "print(\"🎥 DIRECTOR DEEP DIVE\")\n",
    "print(\"=\"*60)\n",
    "print(response.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cleanup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fetch_mcp.close()\n",
    "memory_mcp.close()\n",
    "print(\"✓ Servers closed - your movie preferences are saved!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Recap of what we did above\n",
    "\n",
    "Behind the scenes, aisuite few things:\n",
    "- ✅ **Converted MCP tool schemas** to OpenAI-compatible format\n",
    "- ✅ **Handled tool execution** when the LLM requested them\n",
    "- ✅ **Managed async operations** for MCP server communication\n",
    "\n",
    "MCP Tools\n",
    "**Web search** - LLM could do web search due to Fetch being passed as a tool.\n",
    "**Preserved your data in knowledge graph** - LLM could store your preferences and look it using server-memory being passed as a tool.\n",
    "\n",
    "You, as an user, just wrote natural prompts - aisuite handled all the tool calling complexity - LLM returned personalized recommendations.\n",
    "\n",
    "You built a **personalized movie assistant** that:\n",
    "- ✅ Researches movies from the web\n",
    "- ✅ Learns your preferences over time\n",
    "- ✅ Gives smart recommendations\n",
    "- ✅ Remembers everything across sessions\n",
    "- ✅ Builds a knowledge graph of your tastes\n",
    "\n",
    "**All with minimal code!**\n",
    "\n",
    "## Try These Next\n",
    "\n",
    "Now that you've got the basics, explore more capabilities:\n",
    "\n",
    "### 🎭 Refine Your Taste Profile\n",
    "```python\n",
    "# Tell it what you DON'T like to improve recommendations\n",
    "response = client.chat.completions.create(\n",
    "    model=\"openai:gpt-4o\",\n",
    "    messages=[{\"role\": \"user\", \"content\": \"\"\"Store in memory that I didn't enjoy:\n",
    "        - 'Transformers' movies (too much action, not enough plot)\n",
    "        - 'Scary Movie' series (slapstick comedy isn't my thing)\n",
    "        \n",
    "        Then suggest 3 movies I WOULD like based on my updated profile.\"\"\"}],\n",
    "    tools=memory_mcp.get_callable_tools(),\n",
    "    max_turns=5\n",
    ")\n",
    "```\n",
    "\n",
    "### 📊 Query Your Complete Watch History\n",
    "```python\n",
    "# See everything the assistant remembers\n",
    "response = client.chat.completions.create(\n",
    "    model=\"openai:gpt-4o\",\n",
    "    messages=[{\"role\": \"user\", \"content\": \"\"\"Search your memory and tell me:\n",
    "        1. What movies do I love?\n",
    "        2. What movies do I dislike?\n",
    "        3. What are my key preferences (genres, themes, directors)?\n",
    "        4. Based on all this, what's ONE perfect movie recommendation?\"\"\"}],\n",
    "    tools=memory_mcp.get_callable_tools(),\n",
    "    max_turns=5\n",
    ")\n",
    "```\n",
    "\n",
    "### 🔍 Explore Your Memory File\n",
    "```python\n",
    "# See the raw knowledge graph\n",
    "import json\n",
    "with open(memory_file, 'r') as f:\n",
    "    for line in f.readlines()[:10]:\n",
    "        entry = json.loads(line)\n",
    "        print(f\"{entry.get('type')}: {entry.get('name')}\")\n",
    "```\n",
    "\n",
    "### 🌟 More Fun Queries\n",
    "- \"Find me a thriller like 'Gone Girl'\"\n",
    "- \"What are the best movies of 2024?\"\n",
    "- \"Research Greta Gerwig's films and recommend one\"\n",
    "- \"I'm in the mood for something uplifting - what should I watch?\"\n",
    "- \"Based on my taste, should I watch [specific movie]?\"\n",
    "- \"Find me a hidden gem from the 90s I might have missed\"\n",
    "\n",
    "## The Pattern\n",
    "\n",
    "Setup MCP tools, and call chat.completions.create() with max_turns.\n",
    "\n",
    "```python\n",
    "# 1. Set up fetch + memory\n",
    "fetch_mcp = MCPClient(command=\"uvx\", args=[\"mcp-server-fetch\"])\n",
    "memory_mcp = MCPClient(\n",
    "    command=\"npx\",\n",
    "    args=[\"-y\", \"@modelcontextprotocol/server-memory\"],\n",
    "    env={\"MEMORY_FILE_PATH\": \"movie_memory.jsonl\"}\n",
    ")\n",
    "\n",
    "# 2. Combine tools\n",
    "tools = fetch_mcp.get_callable_tools() + memory_mcp.get_callable_tools()\n",
    "\n",
    "# 3. Chat naturally!\n",
    "response = client.chat.completions.create(\n",
    "    model=\"openai:gpt-4o\",\n",
    "    messages=[{\"role\": \"user\", \"content\": \"Research X and remember Y\"}],\n",
    "    tools=tools,\n",
    "    max_turns=5\n",
    ")\n",
    "```\n",
    "\n",
    "## Other Ideas\n",
    "\n",
    "Use this same pattern for:\n",
    "- 🍳 **Recipe assistant** that learns your dietary preferences (see `recipe_chef_assistant.ipynb`)\n",
    "- ✈️ **Travel planner** that remembers your bucket list\n",
    "- 📚 **Book recommender** that tracks your reading history\n",
    "- 🎮 **Game advisor** that knows your favorite genres\n",
    "- 🎵 **Music discovery** that learns your taste\n",
    "\n",
    "## Resources\n",
    "\n",
    "- **Fetch Server**: https://github.com/modelcontextprotocol/servers/tree/main/src/fetch\n",
    "- **Memory Server**: https://github.com/modelcontextprotocol/servers/tree/main/src/memory\n",
    "- **aisuite Documentation**: https://github.com/andrewyng/aisuite\n",
    "- **More MCP Servers**: https://github.com/modelcontextprotocol/servers\n",
    "\n",
    "**Your movie preferences persist across sessions** - restart this notebook anytime and your assistant will remember everything! 🎬✨\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
